package com.wumai.modernguilib.component;

import com.mojang.blaze3d.matrix.MatrixStack;
import net.minecraft.client.Minecraft;
import org.lwjgl.glfw.GLFW;

public abstract class BaseComponent {
    protected int x, y, width, height;
    protected boolean visible = true;
    protected boolean enabled = true;
    protected BaseComponent parent = null; // 父组件引用
    protected float[] paddings = new float[]{0f, 0f, 0f, 0f};

    protected interface PaddingPosition {
        int TOP = 0;
        int RIGHT = 1;
        int BOTTOM = 2;
        int LEFT = 3;
    }

    public BaseComponent() {

    }

    public BaseComponent(int x, int y, int width, int height) {
        this.x = x;
        this.y = y;
        this.width = width;
        this.height = height;
    }

    // 钩子方法，供子类重写
    protected void onBeforeRender(MatrixStack matrixStack, int mouseX, int mouseY, float partialTicks) {
        // 默认实现为空
    }

    protected void onAfterRender(MatrixStack matrixStack, int mouseX, int mouseY, float partialTicks) {
        // 默认实现为空
    }

    protected abstract void renderContent(MatrixStack matrixStack, int mouseX, int mouseY, float partialTicks);

    protected abstract void renderBackground(MatrixStack matrixStack, int mouseX, int mouseY, float partialTicks);

    /**
     * 请勿重写这个方法
     * */
    protected void renderChildren(MatrixStack matrixStack, int mouseX, int mouseY, float partialTicks) {

    }

    public final void render(MatrixStack matrixStack, int mouseX, int mouseY, float partialTicks) {
        onBeforeRender(matrixStack, mouseX, mouseY, partialTicks);
        renderBackground(matrixStack, mouseX, mouseY, partialTicks);
        renderContent(matrixStack, mouseX, mouseY, partialTicks);
        renderChildren(matrixStack, mouseX, mouseY, partialTicks);
        onAfterRender(matrixStack, mouseX, mouseY, partialTicks);
    }

    // 将鼠标坐标转换为NDC坐标进行比较
    public boolean isMouseOver(double mouseX, double mouseY) {
        // mouseX和mouseY已经是NDC坐标，直接比较
        return mouseX >= x && mouseX < x + width && mouseY >= y && mouseY < y + height;
    }

    // 获取当前屏幕宽度的辅助方法
    protected int getCurrentScreenWidth() {
        return Minecraft.getInstance().getWindow().getGuiScaledWidth();
    }

    // 获取当前屏幕高度的辅助方法
    protected int getCurrentScreenHeight() {
        return Minecraft.getInstance().getWindow().getGuiScaledHeight();
    }


    /**
     * 这是默认的处理，即判断此组件是否显示且启用，且判断此时鼠标坐标是否在组件范围内
     * 这里的boolean值指的是该组件是否处理了该事件，如果处理了返回true，在递归的时候
     * 别的组件就不会再处理了，也就是说鼠标点击事件只处理一次，后续的鼠标移动事件将不再处理
     * @param mouseX 鼠标X坐标(NDC)
     * @param mouseY 鼠标Y坐标(NDC)
     * @param button 鼠标按键
     * @return 是否处理了该事件
     */
    public boolean mouseClicked(double mouseX, double mouseY, int button) {
        if (!visible || !enabled) {
            return false;
        }
        if (isMouseOver(mouseX, mouseY) && button == GLFW.GLFW_MOUSE_BUTTON_1) {
            return true;
        }
        return false;
    }

    /**
     * 鼠标释放事件处理方法，将事件传递给子组件
     * @param mouseX 鼠标X坐标(NDC)
     * @param mouseY 鼠标Y坐标(NDC)
     * @param button 鼠标按键
     * @return 是否处理了该事件
     */
    public boolean mouseReleased(double mouseX, double mouseY, int button) {
        if (!visible || !enabled) {
            return false;
        }
        if (isMouseOver(mouseX, mouseY) && button == GLFW.GLFW_MOUSE_BUTTON_1) {
            return true;
        }
        return false;
    }
    
    /**
     * 鼠标拖拽事件处理方法
     * @param mouseX 鼠标X坐标(NDC)
     * @param mouseY 鼠标Y坐标(NDC)
     * @param button 鼠标按键
     * @param dragX 拖拽X距离
     * @param dragY 拖拽Y距离
     * @return 是否处理了该事件
     */
    public boolean mouseDragged(double mouseX, double mouseY, int button, double dragX, double dragY) {
        if (!visible || !enabled) {
            return false;
        }
        if (isMouseOver(mouseX, mouseY) && button == GLFW.GLFW_MOUSE_BUTTON_1) {
            return true;
        }
        return false;
    }
    
    /**
     * 鼠标滚轮事件处理方法
     * @param mouseX 鼠标X坐标(NDC)
     * @param mouseY 鼠标Y坐标(NDC)
     * @param delta 滚轮滚动量
     * @return 是否处理了该事件
     */
    public boolean mouseScrolled(double mouseX, double mouseY, double delta) {
        if (!visible || !enabled) {
            return false;
        }
        if (isMouseOver(mouseX, mouseY)) {
            return true;
        }
        return false;
    }

    // 自动设置大小以填充父容器（仅适用于顶级组件）
    public void fillParent() {
        if (parent == null) {
            // 顶级组件，填充整个屏幕(-1到1的NDC坐标范围)
            this.x = 0;
            this.y = 0;
            this.width = getCurrentScreenWidth();
            this.height = getCurrentScreenHeight();
        }
    }
    
    /**
     * 当组件被添加到父容器时调用此方法，用于自动计算位置和大小
     * 子类可以重写此方法以实现特定的布局逻辑
     * @param parent 父容器
     */
    public void onAddedToParent(BaseComponent parent) {
        // 默认实现为空，子类可以根据需要重写
    }
    
    /**
     * 当父容器的布局发生变化时调用此方法
     * 子类可以重写此方法以响应布局变化
     */
    public void onParentLayoutChanged() {
        updateLayout();
    }

    // 实际上这个是用于调整该组件下的样式信息，但是不包括例如鼠标移动到上面时的渲染这种
    // 仅仅改变其
    public abstract void updateLayout();

    // 设置padding (参考CSS/Vue风格)
    public void setPadding(float padding) {
        // 单个值，应用到所有边
        this.paddings[0] = padding; // 上
        this.paddings[1] = padding; // 右
        this.paddings[2] = padding; // 下
        this.paddings[3] = padding; // 左
    }

    public void setPadding(float vertical, float horizontal) {
        // 两个值，第一个用于上下，第二个用于左右
        this.paddings[0] = vertical;   // 上
        this.paddings[1] = horizontal; // 右
        this.paddings[2] = vertical;   // 下
        this.paddings[3] = horizontal; // 左
    }

    public void setPadding(float top, float right, float bottom, float left) {
        // 四个值
        this.paddings[0] = top;
        this.paddings[1] = right;
        this.paddings[2] = bottom;
        this.paddings[3] = left;
    }

    // Getters and setters
    public float getX() { return x; }
    public void setX(int x) { this.x = x; }

    public float getY() { return y; }
    public void setY(int y) { this.y = y; }

    public float getWidth() { return width; }
    public void setWidth(int width) { this.width = width; }

    public float getHeight() { return height; }
    public void setHeight(int height) { this.height = height; }

    public boolean isVisible() { return visible; }
    public void setVisible(boolean visible) { this.visible = visible; }

    public boolean isEnabled() { return enabled; }
    public void setEnabled(boolean enabled) { this.enabled = enabled; }

    public BaseComponent getParent() { return parent; }
    public void setParent(BaseComponent parent) { this.parent = parent; }

    public float[] getPaddings() { return paddings; }
}